#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

int main() {
  fprintf(
    stderr,
    "This demo shows the contents of the chunk metadata.\n"
    "\n"
    "First, let's allocate four chunks:\n"
    "\n"
  );

  char* ptrs[4];
  size_t i;
  for (i = 0; i < 4; i++) {
    ptrs[i] = malloc(0x800);
    assert(i == 0 || ptrs[i] == 0x810 + ptrs[i-1]); // chunks are adjacent
    fprintf(stderr, "Chunk %lu: %p\n", i, ptrs[i]);
    memset(ptrs[i], 0, 0x800);
  }

  fprintf(stderr, "\nNow, let's free Chunk 2.\n\n");
  free(ptrs[2]);

  fprintf(stderr, "This is what the metadata looks like now:\n\n");

  for (i = 0; i < 4; i++) {
    size_t* p = (size_t*)ptrs[i];
    size_t* metadata = p - 2;
    fprintf(
      stderr,
      "Chunk %lu:\n"
      "%p:  %.16lx %.16lx  (metadata)\n"
      "%p:  %.16lx %.16lx  (user data)\n"
      "%p:  %.16lx %.16lx  (user data)\n"
      "\n",
      i,
      metadata, metadata[0], metadata[1],
      metadata+2, metadata[2], metadata[3],
      metadata+4, metadata[4], metadata[5]
    );
  }

  fprintf(
    stderr,
    "Notice the differences around Chunk 2, which we freed:\n"
    "\n"
    "1. It has been put on a freelist, so its body contains two pointers:\n"
    "   the forward and back pointers in a doubly-linked list.\n"
    "\n"
    "2. The metadata after Chunk 2 has been modified to indicate\n"
    "   that Chunk 2 is free.\n"
  );

  return 0;
}
